#include <mockcpp/mockcpp.hpp>
#include <testngpp/testngpp.hpp>
#include <math.h>
#include <limits>
#include <Square.h>

USING_MOCKCPP_NS
USING_TESTNGPP_NS

namespace
{
const float deltaThreshold = std::numeric_limits<float>::epsilon();
}

FIXTURE(Square_isValid)
{
    TEST(should be able to check it is valid when border is valid )
    {
        Square square(2);
        ASSERT_EQ(true, square.isValid());
    }
    
    TEST(should be able to check it is invalid when border is 0)
    {
        Square square(0);
        ASSERT_EQ(false, square.isValid());
    }  
    
    TEST(should be able to check it is invalid when border is minus)
    {
        Square square(-1);
        ASSERT_EQ(false, square.isValid());
    }
   
    TEST(should be able to check it is invalid when border is larger than 75)
    {
        Square square(75.1);
        ASSERT_EQ(false, square.isValid());
    }
    
    TEST(should be able to check it is invalid when border is equal to 75)
    {
        Square square(75);
        ASSERT_EQ(false, square.isValid());
    }  
    
    TEST(should be able to check it is valid when border is smaller than 75)
    {
        Square square(74.99);
        ASSERT_EQ(true, square.isValid());
    }
};

FIXTURE(Square_getArea)
{    
    TEST(should be able to cal area : 2*2=4)
    {
        Square square(2);
        ASSERT_EQ(4, square.getArea());
    }
    
    TEST(should be able to calc area : 2.5*2.5=6.25)
    {
        Square square(2.5);
        ASSERT_DELTA(6.25, square.getArea(), deltaThreshold);
    }
    
    TEST(should be able to trunc width and height : 2.502*2.502=6.25)
    {
        Square square(2.502);
        ASSERT_DELTA(6.25, square.getArea(), deltaThreshold);
    }
    
    TEST(should be able to round area when the decimal part smaller than 0.5: 2.534*2.534=6.40)
    {
        Square square(2.534);
        ASSERT_DELTA(6.40, square.getArea(), deltaThreshold);
    }
    
    TEST(should be able to round area when the decimal part more than 0.5: 3.14*3.14=9.86)
    {
        Square square(3.14);
        ASSERT_DELTA(9.86, square.getArea(), deltaThreshold);
    }
    
    TEST(area should be 0 when it is invalid (minus)) 
    {
        Square square(-1);
        ASSERT_EQ(0, square.getArea());
    }
   
    TEST(area should be 0 when it is invalid (larger than 75)) 
    {
        Square square(105);
        ASSERT_EQ(0, square.getArea());
    }

};

FIXTURE(Square_getPerimeter)
{
    TEST(should be able to calc perimeter: 2*(2.1+2.1)=8.4)
    {
        Square square(2.1);
        ASSERT_DELTA(8.4, square.getPerimeter(), deltaThreshold);
    } 
    
    TEST(should be able to calc perimeter: 2*(6.333+6.333)=25.32)
    {
        Square square(6.333);
        ASSERT_DELTA(25.32, square.getPerimeter(), deltaThreshold);
    } 
      
    TEST(should be able to calc perimeter: 2*(2+2)=8)
    {
        Square square(2);
        ASSERT_EQ(8, square.getPerimeter());
    }    
    
    TEST(perimeter should be 0 when it is invalid (minus)) 
    {
        Square square(-1);
        ASSERT_EQ(0, square.getPerimeter());
    }
    
    TEST(perimeter should be 0 when it is invalid (larger than 75)) 
    {
        Square square(105);
        ASSERT_EQ(0, square.getPerimeter());
    }
};


FIXTURE(Square_setBorder)
{
    TEST(set a invalid new border, the area should be same to before (before is valid))
    {
        Square square(10);
        ASSERT_EQ(100, square.getArea());
        
        square.setBorder(80);
        ASSERT_EQ(100, square.getArea());
    }
    
    TEST(set a invalid new border, the area should be same to before (before is invalid))
    {
        Square square(0);
        ASSERT_EQ(0, square.getArea());
        
        square.setBorder(80);
        ASSERT_EQ(0, square.getArea());
    }
    
    TEST(set a valid new border, the area should be changed)
    {
        Square square(10);   
        ASSERT_EQ(100, square.getArea());
             
        square.setBorder(50);
        ASSERT_EQ(2500, square.getArea());
    }   
};

